package org.yx.service.smfr.pass_product_sn;

import java.util.List;

import org.dbist.dml.Query;
import org.yx.exception.BizException;
import org.yx.models.MbasCdsDtl;
import org.yx.models.SmfrOprDef;
import org.yx.models.SmfrOrdDef;
import org.yx.models.SmfrProPth;
import org.yx.models.SmfrPsnSts;
import org.yx.models.SmfrPthOpr;
import org.yx.service.bas.view_common_data_setup_detail.BasViewCommonDataSetupDetailIn;
import org.yx.service.bas.view_common_data_setup_detail.BasViewCommonDataSetupDetailService;
import org.yx.service.smfr.insert_product_serial_history.SmfrInsertProductSerialHistoryIn;
import org.yx.service.smfr.insert_product_serial_history.SmfrInsertProductSerialHistoryService;
import org.yx.utils.BaseService;
import org.yx.utils.FieldMap;
import org.yx.utils.ServiceBeanUtil;

import com.xiaoleilu.hutool.collection.CollUtil;
import com.xiaoleilu.hutool.util.NumberUtil;
import com.xiaoleilu.hutool.util.StrUtil;

/**
 * 产品批次工序过站
 * 
 * @author zxw
 * @since 2019/04/20
 **/
public class SmfrPassProductSnService extends BaseService {
	public SmfrPassProductSnOut passProductSn(SmfrPassProductSnIn in) throws Exception {
		checkStringNotBlank(in, "mo,lineId,psn,oper");

		SmfrOrdDef order = selectOne(SmfrOrdDef.class, in.getUserOrgCode(), in.getMo());
		if (order == null || order.getMoStatus() == 'D') {
			throw new BizException("SMFR-0004", "生产工单${mo}不存在或已被删除。", FieldMap.of("mo", in.getMo()));
		}

		if ('P' != order.getMoStatus()) {
			throw new BizException("SMFR-0008", "当生产工单${mo}的状态是${moStatus}，此操作是无效的。", FieldMap.of("mo", order.getMo()),
					FieldMap.of("moStatus", order.getMoStatus()));
		}

		if (StrUtil.isBlank(order.getPathCode())) {
			throw new BizException("SMFR-0009", "生产工单${mo}的工艺路线或工序不存在。", FieldMap.of("mo", order.getMo()));
		}

		if (!StrUtil.equals(order.getLineCode(), in.getLineCode())) {
			throw new BizException("SMFR-0011", "此生产订单${mo}不属于此生产线${lineCode}。", FieldMap.of("mo", order.getMo()),
					FieldMap.of("lineCode", in.getLineCode()));
		}

		SmfrPsnSts psnSts = selectOneLocked(SmfrPsnSts.class, order.getOrgCode(), in.getPsn());
		if (psnSts == null || psnSts.getStatus() == 'D') {
			throw new BizException("SMFR-0010", "产品批号${psn}不存在或已删除。", FieldMap.of("psn", in.getPsn()));
		}
		if (psnSts.getStatus() == 'C') {// Create status
			psnSts.setStatus('P');// Process status
		}

		if (psnSts.getStatus() != 'P') {
			BasViewCommonDataSetupDetailIn cdsIn = new BasViewCommonDataSetupDetailIn();
			cdsIn.setGroupName("PSN_EVENT");
			cdsIn.setKey1(psnSts.getEventCode());
			List<MbasCdsDtl> cdsDtlList = ServiceBeanUtil.getBean(BasViewCommonDataSetupDetailService.class)
					.viewCommonDataSetupDetail(cdsIn).getCdsDtlList();
			String eventDesc = CollUtil.isNotEmpty(cdsDtlList) ? cdsDtlList.get(0).getData1() : "";
			cdsIn.setGroupName("PSN_STATUS");
			cdsIn.setKey1(psnSts.getStatus().toString());
			cdsDtlList = ServiceBeanUtil.getBean(BasViewCommonDataSetupDetailService.class)
					.viewCommonDataSetupDetail(cdsIn).getCdsDtlList();
			String psnStatusDesc = CollUtil.isNotEmpty(cdsDtlList) ? cdsDtlList.get(0).getData1() : "";

			throw new BizException("SMFR-0012", "产品批号${psn}在状态${status}以及事件${event}下，当前操作不允许。", FieldMap.of("psn",
					psnSts.getPsn()), FieldMap.of("status", psnSts.getStatus() + "(" + psnStatusDesc + ")"),
					FieldMap.of("event", psnSts.getEventCode() + "(" + eventDesc + ")"));
		}

		if (StrUtil.isNotBlank(in.getOper()) && !StrUtil.equals(in.getOper(), psnSts.getOper())) {
			throw new BizException("SMFR-0015", "产品批号${psn}当前工序是${oper}。", FieldMap.of("psn", psnSts.getPsn()),
					FieldMap.of("oper", psnSts.getOper()));
		}

		SmfrProPth path = selectOne(SmfrProPth.class, order.getOrgCode(), order.getPathCode());
		if (path == null || 'D' == path.getPathStatus()) {
			throw new BizException("SMFR-0002", "工艺路线${pathCode}不存在或已经删除。",
					FieldMap.of("pathCode", order.getPathCode()));
		}

		Query query = new Query();
		query.addFilter("orgCode", order.getOrgCode());
		query.addFilter("pathCode", path.getPathCode());
		query.addFilter("status", 'N');
		query.addOrder("seqNum", true);
		List<SmfrPthOpr> operList = selectList(SmfrPthOpr.class, query);
		if (CollUtil.isEmpty(operList)) {
			throw new BizException("SMFR-0005", "工艺路线${pathCode}的工序不存在。", FieldMap.of("pathCode", path.getPathCode()));
		}

		int index = -1;
		for (int i = 0; i < operList.size(); i++) {
			if (operList.get(i).getSeqNum().equals(psnSts.getOperSeq())
					&& operList.get(i).getOper().equals(psnSts.getOper())) {
				index = i;
				break;
			}
		}

		if (index < 0) {
			throw new BizException("SMFR-0013", "产品批号${psn}无法匹配到当前工序${oper}的信息。", FieldMap.of("psn", psnSts.getPsn()),
					FieldMap.of("oper", psnSts.getOper()));
		} else {
			SmfrOprDef oper = selectOne(SmfrOprDef.class, operList.get(index).getOrgCode(), operList.get(index)
					.getOper());
			if (oper == null || oper.getOperStatus() == 'D') {
				throw new BizException("SMFR-0001", "工序${oper}不存在或已经删除。", FieldMap.of("oper", operList.get(index)
						.getOper()));
			} else if ('H' == oper.getOperStatus()) {
				throw new BizException("SMFR-0014", "工序${oper}当前状态是品质锁定状态。", FieldMap.of("oper", oper.getOper()));
			}

			psnSts.setMo(order.getMo());
			psnSts.setMatCode(order.getMatCode());
			psnSts.setMatVer(order.getMatVer());
			psnSts.setDtlSeq(psnSts.getDtlSeq() + 1);
			psnSts.setPathCode(path.getPathCode());
			psnSts.setQty(in.getQty() == null ? psnSts.getQty() : in.getQty());
			psnSts.setEventCode("MOVE");
			psnSts.setEventValue("M");
			psnSts.setCurrentLoc(order.getLineCode());
			if (index == operList.size() - 1) {
				// 最后一道工序过站只增工序序列，不变工序
				psnSts.setOperSeq(operList.get(index).getSeqNum() + 1);
				psnSts.setStatus('F');
			} else {
				psnSts.setOperSeq(operList.get(index + 1).getSeqNum());
				psnSts.setOper(operList.get(index + 1).getOper());
			}

			update(psnSts, "mo,matCode,matVer,status,dtlSeq,operSeq,oper,pathCode,qty,eventCode,eventValue,currentLoc");

			SmfrInsertProductSerialHistoryIn hisIn = new SmfrInsertProductSerialHistoryIn();
			hisIn.setPsnSts(psnSts);
			ServiceBeanUtil.getBean(SmfrInsertProductSerialHistoryService.class).insertProductSerialHistory(hisIn);

			// auto move oper
			while (true) {
				// 查找条码后序工序是否自动过站
				index = -1;
				for (int i = 0; i < operList.size(); i++) {
					if (operList.get(i).getSeqNum().equals(psnSts.getOperSeq())
							&& operList.get(i).getOper().equals(psnSts.getOper())) {
						index = i;
						break;
					}
				}

				if (index < 0) {
					break;
				}

				SmfrOprDef nextOper = selectOne(SmfrOprDef.class, psnSts.getOrgCode(), operList.get(index).getOper());
				if (nextOper == null || nextOper.getOperStatus() == 'D') {
					throw new BizException("SMFR-0001", "工序${oper}不存在或已经删除。", FieldMap.of("oper", psnSts.getOper()));
				} else if ('H' == nextOper.getOperStatus()) {
					throw new BizException("SMFR-0014", "工序${oper}当前状态是品质锁定状态。", FieldMap.of("oper", psnSts.getOper()));
				}

				if ('Y' == nextOper.getAutoMove()) {
					psnSts.setDtlSeq(psnSts.getDtlSeq() + 1);
					psnSts.setEventCode("MOVE");
					psnSts.setEventValue("A");
					if (index == operList.size() - 1) {
						// 最后一道工序过站只增工序序列，不变工序
						psnSts.setOperSeq(operList.get(index).getSeqNum() + 1);
						psnSts.setStatus('F');
					} else {
						psnSts.setOperSeq(operList.get(index + 1).getSeqNum());
						psnSts.setOper(operList.get(index + 1).getOper());
					}

					update(psnSts, "status,dtlSeq,operSeq,oper,eventCode,eventValue");

					hisIn.setPsnSts(psnSts);
					ServiceBeanUtil.getBean(SmfrInsertProductSerialHistoryService.class).insertProductSerialHistory(
							hisIn);

					if (index == operList.size() - 1) {
						// 已经移动到最后工序
						break;
					}
				} else {
					// 紧临后序工序不是自动过站，中止
					break;
				}
			}

			if ('F' == psnSts.getStatus()) {
				//最后产品完工
				order.setOutQty(NumberUtil.add(order.getOutQty(), psnSts.getQty()));

				update(order, "outQty");
			}
		}

		SmfrPassProductSnOut out = new SmfrPassProductSnOut();

		return out;
	}
}